home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i053: 2.11 News Source, Part04/09
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!rick (Rick Adams)
- Mod.sources: Volume 7, Issue 53
- Archive-name: 2.11news/Part14
-
- # To extract, sh this file
- #
- # news 2.11 source part 4 of 9
- #
- if test ! -d src
- then
- mkdir src
- fi
- echo x - src/postnews.c 1>&2
- sed 's/.//' >src/postnews.c <<'*-*-END-of-src/postnews.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * Postnews: post a news message to Usenet. This C version replaces a shell
- - * script, and does more intelligent prompting and filtering than possible
- - * in a shell script.
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)postnews.c 1.28 10/23/86";
- -#endif /* SCCSID */
- -
- -#include "params.h"
- -
- -#define APPEND 1
- -#define REPLACE 2
- -
- -extern char *MAILPARSER;
- -
- -char tempfname[50]; /* file name used for making article */
- -char original[BUFLEN]; /* file name of original, used in followup */
- -char homedir[BUFLEN]; /* HOME environment setting */
- -char user[SBUFLEN]; /* user name */
- -char ccname[BUFLEN]; /* file name for article copy */
- -
- -/* article header information */
- -char subject[BUFLEN];
- -char distribution[BUFLEN];
- -char references[BUFLEN];
- -char newsgroups[BUFLEN];
- -char isfrom[BUFLEN];
- -char msgid[BUFLEN];
- -char keywords[BUFLEN];
- -char summary[BUFLEN];
- -
- -char ngsep[] = { NGDELIM, '\0' }; /* == "," */
- -
- -char *Progname = "postnews"; /* for xerror */
- -
- -time_t fmodtime;
- -char buf[BUFLEN];
- -
- -#define MAXDISTR 16
- -struct distr {
- - char abbr[24];
- - char descr[128];
- -} distr[MAXDISTR];
- -
- -FILE *xfopen();
- -
- -main(argc, argv)
- -char *argv[];
- -{
- - register int c;
- -
- - init();
- -
- - if (argc == 2) {
- - if (!prefix(argv[1], SPOOL))
- - xerror("Can only followup to articles in %s", SPOOL);
- - followup(argv[1]);
- - (void) strcpy(original, argv[1]);
- - } else
- - if (askyes("Is this message in response to some other message? ","no")) {
- - char ng[BUFLEN], num[BUFLEN];
- - long i, j, lastnum;
- - register char *p;
- - int fd, dir;
- - char canpost;
- -
- - getpr("In what newsgroup was the article posted? ",ng);
- - if (!valid_ng(ng, &i, &j, &canpost))
- - if (canpost == 'i' )
- - byebye("There is no such newsgroup.");
- - else if (canpost == 'n')
- - byebye("You are not allowed to post to that group.");
- -
- - printf("Valid article numbers are from %ld to %ld\n", j, i);
- - lastnum = i + 1;
- - dir = -1;
- -
- - for(;;) {
- - getpr("\nWhat was the article number? ", num);
- - switch(num[0]) {
- - case '+':
- - dir = 1;
- - sprintf(num, "%ld", lastnum + 1);
- - break;
- - case '-':
- - dir = -1;
- - /* no break */
- - case '\0':
- - sprintf(num, "%ld", lastnum + dir);
- - break;
- - }
- - (void) sprintf(original, "%s/%s", SPOOL, ng);
- - for (p=original+strlen(SPOOL)+1; *p ;++p)
- - if (*p == '.')
- - *p = '/';
- - (void) strcat(original, "/");
- - (void) strcat(original, num);
- -
- - if ((fd=open(original,0)) >= 0) {
- - (void) close(fd);
- - printf("\narticle %s\n", original);
- - if (article_line(original, "From: ", buf))
- - printf("%s\n", buf);
- - if (article_line(original, "Subject: ", buf))
- - printf("%s\n", buf);
- - if (askyes("Is this the one you want? ", "n"))
- - break;
- - } else
- - printf("I can't find that article.\n");
- - lastnum = atol(num);
- - }
- -
- - followup(original);
- - } else {
- - do {
- - getpr("Subject: ", subject);
- - if (*subject == '?') {
- -printf("People read the subject line to learn what your article is about.\n");
- -printf("You want it to do the same job as a newspaper headline.\n");
- -printf("So type in something both brief and descriptive.\n");
- - *subject = '\0';
- - }
- - } while (*subject == '\0');
- - getpr("Keywords: ", keywords);
- -
- - while (!get_newsgroup())
- - ;
- - get_distribution((char *)0);
- - }
- -
- - if (pre_checks())
- - exit(1);
- -
- - prep_article();
- - c = 'e';
- - for (;;) {
- - if (c == 'e') {
- - edit_article();
- - post_checks();
- - }
- - do {
- - do {
- - getpr("\nWhat now? [send, edit, list, quit, write] ", buf);
- - c = buf[0];
- - } while (c == '\0');
- - if (isupper(c))
- - c = tolower(c);
- - if (c == 'q') {
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- - if (c == 'l') {
- - char *pager = getenv("PAGER");
- - char lbuf[BUFLEN];
- - if (pager == NULL || *pager == '\0') {
- -#ifdef PAGE
- -# ifdef IHCC
- - (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE);
- -# else /* !IHCC */
- - (void) strcpy(lbuf, PAGE);
- -# endif /* !IHCC */
- - pager = lbuf;
- -#else /* !PAGE */
- - pager = "cat";
- -#endif /* !PAGE */
- - }
- - sprintf(buf, "exec %s %s", pager, tempfname);
- - (void) system(buf);
- - }
- - if (c == 'w') {
- - register int ifd, ofd, nbytes;
- - char iobuf[BUFSIZ];
- - char fname[BUFLEN];
- - getpr("Filename? ", fname);
- - if (fname[0] == '\0')
- - continue;
- - ofd = creat(fname, 0666);
- - if (ofd < 0)
- - perror(fname);
- - else {
- - ifd = open(tempfname, 0);
- - if (ifd < 0)
- - xerror("Can't reopen %s\n", tempfname);
- - while ((nbytes = read(ifd, iobuf, BUFSIZ)) > 0 )
- - write(ofd, iobuf, nbytes);
- - close(ofd);
- - close(ifd);
- - }
- - }
- - } while (!index("eps", c));
- - if (c != 'e')
- - post_article(); /* will exit if posted successfully */
- - };
- -}
- -
- -/*
- - * Find out the topic of interest.
- - */
- -get_newsgroup()
- -{
- - int n;
- - long i;
- - char canpost;
- - static int first = 1;
- -
- - printf("Newsgroups (enter one at a time, end with a blank line):\n");
- - if (first) {
- - printf("\nThe most relevant newsgroup should be the first, you should\n");
- - printf("add others only if your article really MUST be read by people\n");
- - printf("who choose not to read the appropriate group for your article.\n");
- - printf("But DO use multiple newsgroups rather than posting many times.\n\n");
- - first = 0;
- - }
- - printf("For a list of newsgroups, type ?\n");
- - n = 0;
- - newsgroups[0] = '\0';
- -
- - for(;;) {
- - getpr("> ", buf);
- - if (buf[0] == '\0')
- - if (n == 0)
- - return FALSE;
- - else
- - return TRUE;
- - if (buf[0] == '?'){
- - char *pager = getenv("PAGER");
- - char lbuf[BUFLEN];
- - if (pager == NULL) {
- -#ifdef PAGE
- -# ifdef IHCC
- - (void) sprintf(lbuf,"%s/bin/%s", logdir(HOME), PAGE);
- -# else /* !IHCC */
- - (void) strcpy(lbuf, PAGE);
- -# endif /* !IHCC */
- - pager = lbuf;
- -#else /* !PAGE */
- - pager = "cat";
- -#endif /* !PAGE */
- - }
- - printf("These are the currently active groups:\n");
- - sprintf(buf, "exec %s %s/newsgroups", pager, LIB);
- - (void) system(buf);
- - continue;
- - }
- - if (valid_ng(buf, &i, &i, &canpost)) {
- - if (n++ != 0)
- - (void) strcat(newsgroups, ngsep);
- - (void) strcat(newsgroups, buf);
- - } else {
- - if (canpost == 'n')
- - printf("You are not allowed to post to %s\n",
- - buf);
- - else if (canpost == 'i')
- - printf("%s is not a valid newsgroup.\n", buf);
- - }
- - }
- -}
- -
- -/*
- - * Find out how widely the author wants the message distributed.
- - */
- -get_distribution(deflt)
- - char *deflt;
- -{
- - register int i;
- - register char *r;
- - char def[BUFLEN];
- - char *lastgroup;
- -
- - lastgroup = newsgroups;
- - (void) strcpy(def, newsgroups);
- - r = index(def, NGDELIM);
- - if (r)
- - *r = '\0';
- - r = index(def, '.');
- - if (r) {
- - *r = '\0';
- - if (strcmp(def, "net") == 0)
- - (void) strcpy(def, "world");
- - } else {
- - distribution[0] = '\0';
- - return;
- - }
- -
- - if (strcmp(def, "to") == 0) {
- - /*
- - * This only works if "to.xx" is the first (or only)
- - * newsgroup, but it usually is ..
- - * Perhaps we should make the distribution be "to.xxx" ??
- - */
- - distribution[0] = '\0';
- - return; /* He's probably testing something */
- - }
- - if (deflt != (char *)0)
- - (void) strcpy(def, deflt);
- - if (ngmatch("net.test", newsgroups))
- - (void) strcpy(def, "local");
- - for(;;) {
- - do {
- - (void) sprintf(buf, "Distribution (default='%s', '?' for help) : ", def);
- - getpr(buf, distribution);
- - if (distribution[0] == '\0') {
- - if (strcmp(def, "*None*") == 0)
- - printf("You must enter a distribution, '?' for help.\n");
- - (void) strcpy(distribution, def);
- - }
- - } while (strcmp(distribution, "*None*") == 0);
- -
- - /* Did the user ask for help? */
- - if (distribution[0] == '?') {
- - printf("How widely should your article be distributed?\n\n");
- - for (i=0; distr[i].abbr[0]; i++)
- - printf("%s\t%s\n", distr[i].abbr, distr[i].descr);
- - printf("\nEnter the word that specifies the distribution that you require.\n");
- - continue;
- - }
- -
- - /* Check that it's a proper distribution */
- - for (i=0; distr[i].abbr[0]; i++) {
- - if (strncmp(distr[i].abbr, distribution, sizeof(distr[0].abbr)) == 0) {
- - register int n;
- - /* Found a match. Do any special rewriting. */
- - r = newsgroups;
- - n = strlen(distribution);
- - /*
- - * A distribution of foo is useless
- - * if all the newsgroups are in foo.all
- - */
- - for (;;) {
- - if (strncmp(r, distribution, n))
- - return;
- - if ((r = index(r, NGDELIM)) == NULL)
- - break;
- - ++r;
- - }
- - distribution[0] = '\0';
- - return;
- - }
- - }
- - if (strcmp(distribution, def) != 0)
- - printf("Type ? for help.\n");
- - else {
- - int once = TRUE;
- -
- - do {
- - r = lastgroup;
- - while (r = index(r, NGDELIM))
- - if (!prefix(++r, def))
- - break;
- - if (r == NULL) {
- - /*
- - * no newsgroups are distribution
- - * names, and user simply will
- - * not type a valid distribution,
- - * assume that the default is OK.
- - */
- - distribution[0] = '\0';
- - return;
- - }
- - lastgroup = r;
- - if (once)
- - printf("Sorry, '%s' is an unknown distribution. Type ? for help.\n", def);
- - once = FALSE;
- - strcpy(def, r);
- - r = index(def, NGDELIM);
- - if (r)
- - *r = '\0';
- - r = index(def, '.');
- - } while (r == NULL);
- - *r = '\0';
- - if (strcmp(def, "net") == 0)
- - strcpy(def, "world");
- - }
- - }
- -}
- -
- -/*
- - * Do sanity checks before the author types in the message.
- - */
- -pre_checks()
- -{
- - if (recording(newsgroups))
- - return 1;
- - return 0;
- -}
- -
- -/*
- - * Set up the temp file with headers.
- - */
- -prep_article()
- -{
- - FILE *tf, *of;
- - struct stat stbuf;
- -
- - (void) strcpy(tempfname, "/tmp/postXXXXXX");
- - (void) mktemp(tempfname);
- -
- - /* insert a header */
- - tf = xfopen(tempfname, "w");
- - fprintf(tf, "Subject: %s\n", subject);
- - fprintf(tf, "Newsgroups: %s\n", newsgroups);
- - if (distribution[0] != '\0' && strcmp(distribution, "world"))
- - fprintf(tf, "Distribution: %s\n", distribution);
- -
- - if (keywords[0] != '\0')
- - fprintf(tf, "Keywords: %s\n", keywords);
- - if (summary[0] != '\0')
- - fprintf(tf, "Summary: %s\n", summary);
- -
- - if (references[0] != '\0') {
- - fprintf(tf, "References: %s\n\n", references);
- -
- - if (askyes("Do you want to include a copy of the article? ", "no")){
- - of = xfopen(original, "r");
- - while (fgets(buf, BUFSIZ, of) != NULL)
- - if (buf[0] == '\n') /* skip headers */
- - break;
- - fprintf(tf, "In article %s, %s writes:\n", msgid, isfrom);
- - while (fgets(buf, BUFSIZ, of) != NULL)
- - fprintf(tf, "> %s", buf);
- - (void) fclose(of);
- - printf("OK, but please edit it to suppress unnecessary verbiage, signatures, etc.\n");
- - }
- - }
- -
- - fprintf(tf, "\n\n");
- - (void) fflush(tf);
- - (void) fstat(fileno(tf), &stbuf);
- - fmodtime = stbuf.st_mtime;
- - (void) fclose(tf);
- -}
- -
- -edit_article()
- -{
- - register char *p;
- - char *editor;
- - char *endflag = "";
- - char *getenv();
- -
- - /* edit the file */
- - editor = getenv("EDITOR");
- - if (editor == NULL)
- - editor = DFTEDITOR;
- -
- - p = editor + strlen(editor) - 2;
- - if (strcmp(p, "vi") == 0)
- - endflag = "+";
- -
- - (void) sprintf(buf, "A=%s;export A;exec %s %s %s",
- - original, editor, endflag, tempfname);
- -
- - (void) system(buf);
- -}
- -
- -/*
- - * Do sanity checks after the author has typed in the message.
- - */
- -post_checks()
- -{
- - char group[BUFLEN];
- - register char *c, *p;
- - struct stat stbuf;
- -
- - if (stat(tempfname, &stbuf) < 0) {
- - printf("File deleted - no message posted.\n");
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- - if (stbuf.st_size < 5) {
- - printf("File too small (<5 characters) - no message posted.\n");
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- -
- - if (stbuf.st_mtime == fmodtime) {
- - printf("File not modified - no message posted.\n");
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- -
- - /*
- - * Is this the right number? Most of the headers are yet to be added
- - */
- - if (stbuf.st_size > 64000) {
- - printf("\nYour message will probably be truncated when it\n");
- - printf("passes through a notesfile site, since it is\n");
- - printf("greater than 64000 characters.\n\n");
- - if (!askyes("Do you still want to post it? ","")) {
- - sprintf(ccname, "%s/dead.article", homedir);
- - save_article();
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- - }
- -
- - /*
- - * get the newsgroups from the edited article, in
- - * case they were altered in the editor
- - */
- - if (!article_line(tempfname, "Newsgroups: ", group)) {
- - nogroups:
- - printf("Not sending to any newsgroups - no message posted\n");
- - (void) UNLINK(tempfname);
- - exit(1);
- - }
- - c = &group[11];
- - while (*c == ' ' || *c == '\t')
- - c++;
- - if (*c == '\0')
- - goto nogroups;
- - for (p = newsgroups; *c; c++) /* copy to newsgroups, w/o blanks */
- - if (*c != ' ' && *c != '\t')
- - *p++ = *c;
- - *p = '\0';
- -
- - /* Sanity checks for certain newsgroups */
- - if (ngmatch(newsgroups, "all.wanted") && ngmatch(distribution,"net,na,usa,att,btl,eunet,aus")) {
- - printf("Is your message something that might go in your local\n");
- - printf("newspaper, for example a used car ad, or an apartment\n");
- - printf("for rent? ");
- - if (askyes("","")) {
- - printf("It's pointless to distribute your article widely, since\n");
- - printf("people more than a hundred miles away won't be interested.\n");
- - printf("Please use a more restricted distribution.\n");
- - get_distribution("*None*");
- - modify_article(tempfname, "Distribution: ", distribution,REPLACE);
- - }
- - }
- -
- - if (ngmatch(newsgroups, "all.jokes")) {
- - if (askyes("Could this be offensive to anyone? ","")) {
- - getpr("Whom might it offend? ", group);
- - (void) sprintf(buf," - offensive to %s (rot 13)",group);
- - modify_article(tempfname, "Subject: ", buf, APPEND);
- - encode(tempfname);
- - }
- - }
- -
- - if (ngmatch(newsgroups, "net.general")) {
- - if (index(newsgroups, NGDELIM)) {
- - printf("Everybody in the world reads net.general, so it doesn't make\n");
- - printf("sense to post to newsgroups in addition to net.general. If your\n");
- - printf("article belongs in one of these other newsgroups, then you\n");
- - printf("should not post to net.general. If it is important enough\n");
- - printf("for net.general, then you shouldn't post it in other places\n");
- - printf("as well. Please reenter the newsgroups.\n");
- - while (!get_newsgroup())
- - ;
- - modify_article(tempfname, "Newsgroups: ", newsgroups,REPLACE);
- - }
- - if (ngmatch(newsgroups, "net.general")) {
- - printf("net.general is for important announcements.\n");
- - printf("It is not for items for which you couldn't think\n");
- - printf("of a better place - those belong in net.misc.\n");
- - if (!askyes("Are you sure your message belongs in net.general? ","")) {
- - while (!get_newsgroup())
- - ;
- - modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- - }
- - }
- - }
- -
- - if (ngmatch(newsgroups, "net.sources,!net.sources.all")) {
- - if (!article_line(tempfname, "Subject: ", group)) {
- - nosubj:
- - printf("There seems to be no subject for this article.\n");
- - getpr("Subject: ", subject);
- - modify_article(tempfname, "Subject: ", subject, REPLACE);
- - } else {
- - c = &group[8];
- - while (*c == ' ' || *c == '\t')
- - c++;
- - if (*c == '\0')
- - goto nosubj;
- - strcpy(subject, c);
- - }
- - if (ngmatch(newsgroups, "all.wanted") || iswanted(subject)) {
- - printf("Requests for sources should not be posted to any of\n");
- - printf("the net.sources newsgroups, please post such requests\n");
- - printf("to net.wanted.sources only. Please reenter the newsgroups.\n\n");
- - while (!get_newsgroup())
- - ;
- - modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- - }
- - if (ngmatch(newsgroups, "net.sources")) {
- - if (!ngmatch(newsgroups, "net.sources.all") &&
- - stbuf.st_size < (4*1024)) {
- - printf("Your article seems rather small to be a source distribution.\n");
- - if (!askyes("Are you certain that this is really source? ", "")) {
- -
- - while (!get_newsgroup())
- - ;
- - modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- - }
- - }
- - if (index(newsgroups, NGDELIM)) {
- - printf("Sources should be posted to one newsgroup only.\n");
- - printf("Please pick the most appropriate group for your article.\n\n");
- - while (!get_newsgroup())
- - ;
- - modify_article(tempfname, "Newsgroups: ", newsgroups, REPLACE);
- - }
- - }
- - }
- -}
- -
- -iswanted(str)
- -register char *str;
- -{
- - while (*str == ' ')
- - str++;
- -
- - if (prefix(str, "Re:"))
- - return (FALSE);
- -
- - if (isin(str, " wanted ") || isin(str, " can any") ||
- - isin(str, " need ") || isin(str, " please ") || isin(str, " help ")
- - || isin(str, " looking ") || index(str, '?'))
- - return (TRUE);
- -
- - return (FALSE);
- -}
- -
- -isin(str, words)
- -register char *str, *words;
- -{
- - register char *p;
- - register sc, wc;
- -
- - p = words;
- - while (sc = *str++) {
- - if ((wc = *p++) == '\0')
- - return (TRUE);
- - if (wc == ' ') {
- - if (index(".,!?-; \t\n", sc))
- - continue;
- - } else {
- - if (isupper(wc))
- - wc = tolower(wc);
- - if (isupper(sc))
- - sc = tolower(sc);
- - if (wc == sc)
- - continue;
- - }
- - str -= p - words - 1;
- - p = words;
- - }
- - if (*p == '\0')
- - return (TRUE);
- - return (FALSE);
- -}
- -
- -/*
- - * Save a copy of the article in the users NEWSARCHIVE directory.
- - */
- -save_article()
- -{
- - FILE *in, *out;
- - int c;
- - time_t timenow, time();
- - char *today, *ctime();
- - struct stat stbuf;
- - char filename[BUFLEN];
- -
- - if (stat(ccname, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR) {
- - /*
- - * It would be much nicer here to write articles
- - * in MH format (numbered files, in rfc822 format)
- - *
- - * one day ..
- - */
- - (void) sprintf(filename, "%s/author_copy", ccname);
- - (void) strcpy(ccname, filename);
- - }
- - in = xfopen(tempfname, "r");
- - out = xfopen(ccname, "a");
- - timenow = time((time_t)0);
- - today = ctime(&timenow);
- - fprintf(out,"From postnews %s",today);
- - while ((c=getc(in)) != EOF)
- - putc(c, out);
- - putc('\n', out);
- - (void) fclose(in);
- - (void) fclose(out);
- -}
- -
- -/*
- - * Post the article to the net.
- - */
- -post_article()
- -{
- - int status;
- -
- - printf("Posting article...\n");
- - fflush(stdout);
- - (void) sprintf(buf, "exec %s/%s -h < %s", LIB, "inews", tempfname);
- - status = system(buf);
- -
- - if (status) {
- - printf("Article not posted - exit status %d\n", status);
- - return;
- - } else
- - printf("Article posted successfully.\n");
- -
- - if (ccname[0]) {
- - printf("A copy has been saved in %s\n", ccname);
- - save_article();
- - }
- -
- - (void) UNLINK(tempfname);
- - exit(0);
- -}
- -
- -/*
- - * Initialization.
- - */
- -init()
- -{
- - FILE *fd;
- - register char *p;
- - int i;
- - char *getenv();
- - struct passwd *pw;
- -
- - references[0] = '\0';
- - distribution[0] = '\0';
- -
- - uid = getuid();
- - pw = getpwuid(uid);
- - if (pw == NULL) {
- - fprintf(stderr,"You're not in /etc/passwd\n");
- - exit(1);
- - }
- - p = getenv("HOME");
- - if (p == NULL) {
- - p = getenv("LOGDIR");
- - if (p == NULL)
- - p = pw->pw_dir;
- - }
- - (void) strncpy(user, pw->pw_name, SBUFLEN);
- - (void) strcpy(homedir, p);
- -
- - p = getenv("NEWSARCHIVE");
- - if (p != NULL) {
- - if (*p == '\0')
- - sprintf(ccname, "%s/author_copy", homedir);
- - else
- - strcpy(ccname, p);
- - }
- -
- - pathinit();
- - (void) sprintf(buf, "%s/%s", LIB, "distributions");
- - fd = xfopen(buf, "r");
- - for (i=0; i < MAXDISTR; i++) {
- - if (fscanf(fd, "%s %[^\n]", distr[i].abbr, distr[i].descr)
- - != 2)
- - break;
- - }
- - (void) fclose(fd);
- -}
- -
- -/*
- - * Get a yes or no answer to a question. A default may be used.
- - */
- -askyes(msg, def)
- -char *msg, *def;
- -{
- - for(;;) {
- - printf("%s", msg);
- - buf[0] = 0;
- - (void) gets(buf);
- - switch(buf[0]) {
- - case 'y':
- - case 'Y':
- - return TRUE;
- - case 'n':
- - case 'N':
- - return FALSE;
- - case '\0':
- - switch(*def) {
- - case 'y':
- - case 'Y':
- - return TRUE;
- - case 'n':
- - case 'N':
- - return FALSE;
- - }
- - default:
- - printf("Please answer yes or no.\n");
- - }
- - }
- -}
- -
- -/*
- - * Get a character string into buf, using prompt msg.
- - */
- -getpr(msg, bptr)
- -char *msg, *bptr;
- -{
- - static int numeof = 0;
- - printf("%s", msg);
- - (void) gets(bptr);
- - (void) nstrip(bptr);
- - if (feof(stdin)) {
- - if (numeof++ > 3) {
- - fprintf(stderr,"Too many EOFs\n");
- - exit(1);
- - }
- - clearerr(stdin);
- - }
- -}
- -
- -byebye(mesg)
- -char *mesg;
- -{
- - printf("%s\n", mesg);
- - exit(1);
- -}
- -
- -/*
- - * make a modification to the header of an article
- - *
- - * fname -- name of article
- - * field -- header field to modify
- - * line -- modification line
- - * how -- APPEND or REPLACE
- - *
- - * example:
- - * modify_article("/tmp/article" , "Subject:" , "new subject" , REPLACE);
- - *
- - *
- - */
- -modify_article(fname, field, line, how)
- -char *fname, *field, *line;
- -{
- - FILE *fpart, *fptmp;
- - char *temp2fname = "/tmp/postXXXXXX";
- - char lbfr[BUFLEN];
- - register found = FALSE;
- -
- - mktemp(temp2fname);
- -
- - fptmp = xfopen(temp2fname, "w");
- - fpart = xfopen(fname, "r");
- -
- - while (fgets(lbfr, BUFLEN, fpart) != NULL) {
- - if (prefix(lbfr, field)) {
- - found = TRUE;
- - (void) nstrip(lbfr);
- - if (how == APPEND) {
- - /* append to current field */
- - (void) strcat(lbfr, line);
- - (void) strcat(lbfr, "\n");
- - } else
- - /* replace current field */
- - (void) sprintf(lbfr, "%s%s\n", field, line);
- - }
- - (void) fputs(lbfr, fptmp);
- - }
- -
- - fclose(fpart);
- - fclose(fptmp);
- -
- - fptmp = xfopen(temp2fname, "r");
- - fpart = xfopen(fname, "w");
- -
- - if (!found)
- - fprintf(fpart, "%s%s\n", field, line);
- - while (fgets(buf,BUFLEN,fptmp) != NULL)
- - (void) fputs(buf, fpart);
- -
- - (void) fclose(fpart);
- - (void) fclose(fptmp);
- - (void) UNLINK(temp2fname);
- -}
- -
- -
- -/* verify that newsgroup exists, and get number of entries */
- -valid_ng(ng, maxart, minart, canpost)
- -char *ng;
- -long *maxart, *minart;
- -char *canpost;
- -{
- - char ng_check[BUFLEN], ng_read[BUFLEN];
- - FILE *fp;
- -
- - fp = xfopen(ACTIVE, "r");
- - while (fgets(ng_read, BUFLEN, fp) != NULL) {
- - switch (sscanf(ng_read, "%s %ld %ld %c", ng_check, maxart, minart, canpost)) {
- - case 2:
- - *minart = 1;
- - /* fall through */
- - case 3:
- - *canpost = 'y';
- - /* fall through */
- - case 4:
- - break;
- -
- - default:
- - printf("Active file (%s) corrupted. ", ACTIVE);
- - byebye("Seek help!");
- - }
- -
- - if (strcmp(ng_check, ng) == 0) {
- - (void) fclose(fp);
- - if (*canpost != 'n') {
- -#ifdef FASCIST
- - if (uid && uid != ROOTID && fascist(user, ng)) {
- - *canpost = 'n';
- - return FALSE;
- - }
- -#endif FASCIST
- - return TRUE;
- - } else
- - return FALSE;
- - }
- - }
- - *canpost = 'i';
- - *maxart = 0;
- - *minart = 0;
- - (void) fclose(fp);
- - return FALSE;
- -}
- -
- -/* get the line specified by field from an article */
- -article_line(article, field, line)
- -char *article, *field, *line;
- -{
- - FILE *fp;
- - char *c;
- -
- - fp = xfopen(article,"r");
- - while ((c=fgets(line,BUFLEN,fp)) != NULL && !prefix(line, field))
- - if (line[0] == '\n') {
- - c = NULL;
- - break;
- - }
- - (void) fclose(fp);
- - if (c != NULL) {
- - (void) nstrip(line);
- - return TRUE;
- - } else {
- - line[0] = '\0';
- - return FALSE;
- - }
- -}
- -
- -/* get the header information for a followup article */
- -followup(baseart)
- -register char *baseart;
- -{
- - register char *p;
- -
- - /* subject */
- - if (article_line(baseart, "Subject: ", buf)) {
- - p = buf+9;
- - for ( ; ; ) {
- - while (*p == ' ' || *p == '\t')
- - ++p;
- - if ((*p != 'r' && *p != 'R') ||
- - (p[1] != 'e' && p[1] != 'E') ||
- - (p[2] != ':' && p[2] != ' '))
- - break;
- - p += 3;
- - }
- - (void) sprintf(subject, "Re: %s", p);
- - } else {
- - if (article_line(baseart, "From: ", buf))
- - (void) sprintf(subject, "Re: orphan response from %s", buf);
- - else
- - (void) strcpy(subject, "Re: orphan response");
- - }
- -
- - /* newsgroup */
- - if (article_line(baseart, "Newsgroups: ", buf))
- - (void) strcpy(newsgroups, buf+12);
- - if (ngmatch(newsgroups, "net.general"))
- - (void) strcpy(newsgroups,"net.followup");
- - if (ngmatch(newsgroups, "net.sources,!net.sources.all"))
- - (void) strcpy(newsgroups,"net.sources.d");
- - if (ngmatch(newsgroups, "net.jobs")) {
- - printf("net.jobs is for the direct posting of job announcements and requests.\n");
- - printf("it is not for discussion. You followup has been directed to net.misc\n");
- - (void) strcpy(newsgroups,"net.misc");
- - }
- -
- - /* distribution */
- - if (article_line(baseart, "Distribution: ", buf))
- - (void) strcpy(distribution, buf+14);
- -
- - /* references */
- - if (article_line(baseart, "References: ", buf)) {
- - register char *rcp;
- - (void) strcpy(references, buf+12);
- - (void) strcat(references, " ");
- - /* keep the number of references to a reasonable number */
- - rcp = rindex(references, ' '); /* Can not fail */
- - while ((int)(rcp - references) > 70) {
- - while (*--rcp != ' ')
- - ;
- - rcp[1] = '\0';
- - }
- - }
- - if (article_line(baseart, "Message-ID: ", buf)) {
- - (void) strcat(references, buf+12);
- - (void) strcpy(msgid, buf+12);
- - }
- -
- - if (article_line(baseart, "From: ", buf))
- - (void) strcpy(isfrom, buf+6);
- -
- - if (article_line(baseart, "Keywords: ", buf))
- - (void) strcpy(keywords, buf+10);
- -
- - if (article_line(baseart, "Followup-To: ", buf)) {
- - (void) strcpy(newsgroups, buf+13);
- - if (strcmp(newsgroups, "poster") == 0)
- - byebye("Mail followups directly to poster.");
- - }
- -
- - get_summary();
- -}
- -
- -get_summary()
- -{
- - register char *p;
- - register i;
- -
- - printf("Please enter a short summary of your contribution to the discussion\n");
- - printf("Just one or two lines ... (end with a blank line)\n");
- - p = summary;
- - for (i = 0; i < 3; i++) { /* 3 * 80 < 256, should be safe .. */
- - getpr(">\t", p);
- - if (*p == '\0')
- - break;
- - p = index(p, '\0');
- - (void) strcpy(p, "\n\t ");
- - p += 3;
- - }
- - if (p > summary)
- - p[-3] = '\0';
- -}
- -
- -encode(article)
- -char *article;
- -{
- - FILE *fpart, *fphead, *fpcoded;
- - char *headerfile = "/tmp/pheadXXXXXX";
- - char *codedfile = "/tmp/pcodeXXXXXX";
- -
- - (void) mktemp(headerfile);
- - (void) mktemp(codedfile);
- -
- - fpart = xfopen(article, "r");
- -
- - /* place article header in "headerfile" file */
- - fphead = xfopen(headerfile, "w");
- - while (fgets(buf, BUFLEN, fpart) != NULL) {
- - (void) fputs(buf, fphead);
- - if (buf[0] == '\n')
- - break;
- - }
- - (void) fclose(fphead);
- -
- - /* place article body in "codedfile" file */
- - fpcoded = xfopen(codedfile, "w");
- - while (fgets(buf, BUFLEN, fpart) != NULL)
- - (void) fputs(buf, fpcoded);
- - (void) fclose(fpcoded);
- - (void) fclose(fpart);
- -
- - /* encode body and put back together with header */
- - (void) rename(headerfile, article);
- -
- - (void) sprintf(buf,"exec %s/%s 13 < %s >> %s\n", LIB, "caesar", codedfile, article);
- - printf("Encoding article -- please stand by\n");
- - if (system(buf)) {
- - printf("encoding failed");
- - exit(2);
- - }
- - (void) UNLINK(codedfile);
- -}
- -
- -
- -/*
- - * Print a recorded message warning the poor luser what he is doing
- - * and demand that he understands it before proceeding. Only do
- - * this for newsgroups listed in LIBDIR/recording.
- - */
- -recording(ngrps)
- -char *ngrps;
- -{
- - char recbuf[BUFLEN];
- - FILE *fd;
- - char nglist[BUFLEN], fname[BUFLEN];
- - int c, n, yes, retval = 0;
- -
- - (void) sprintf(recbuf, "%s/%s", LIB, "recording");
- - fd = fopen(recbuf, "r");
- - if (fd == NULL)
- - return 0;
- - while ((fgets(recbuf, sizeof recbuf, fd)) != NULL) {
- - (void) sscanf(recbuf, "%s %s", nglist, fname);
- - if (ngmatch(ngrps, nglist)) {
- - (void) fclose(fd);
- - if (fname[0] == '/')
- - (void) strcpy(recbuf, fname);
- - else
- - (void) sprintf(recbuf, "%s/%s", LIB, fname);
- - fd = fopen(recbuf, "r");
- - if (fd == NULL)
- - return 0;
- - while ((c = getc(fd)) != EOF)
- - putc(c, stderr);
- - fprintf(stderr, "Do you understand this? Hit <return> to proceed, <BREAK> to abort: ");
- - n = read(2, recbuf, 100);
- - c = recbuf[0];
- - yes = (c=='y' || c=='Y' || c=='\n' || c=='\n' || c==0);
- - if (n <= 0 || !yes)
- - retval = -1;
- - }
- - }
- - return retval;
- -}
- -
- -xxit(i)
- -{
- - exit(i);
- -}
- -
- -#if !defined(BSD4_2) && !defined(BSD4_1C)
- -rename(from,to)
- -register char *from, *to;
- -{
- - (void) unlink(to);
- - if (link(from, to) < 0)
- - return -1;
- -
- - (void) unlink(from);
- - return 0;
- -}
- -#endif /* !BSD4_2 && ! BSD4_1C */
- *-*-END-of-src/postnews.c-*-*
- echo x - src/control.c 1>&2
- sed 's/.//' >src/control.c <<'*-*-END-of-src/control.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * Control message handling code. Deal with messages which are to be
- - * acted on by netnews itself rather than by people.
- - *
- - * See defs.h "news_version" for the real version of netnews.
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)control.c 2.48 10/30/86";
- -#endif /* SCCSID */
- -
- -#include "iparams.h"
- -
- -#define eq(msg) (strcmp(msg, cargv[0]) == 0)
- -
- -int cargc;
- -char **cargv;
- -
- -FILE *hfopen();
- -FILE *popen(), *mhopen(), *mailhdr();
- -
- -char *senderof();
- -#ifdef u370
- -static struct hbuf htmp;
- -#endif /* u370 */
- -
- -/*
- - * The global structure is initialized to NOTIFY as the default (if defined)
- - * uid to send mail to for every state. The following conditions are
- - * dealt with (assumes NOTIFY defined):
- - *
- - * 1) LIB/notify exists and is empty (or contains no recognizable control
- - * message types).
- - * Action: force TELLME = "";
- - * 2) LIB/notify contains the control message name "all" and no associated
- - * address.
- - * Action: force TELLME = "";
- - * 3) LIB/notify contains the control message name "all" and has an address.
- - * Action: set TELLME = AlloCpy(address);
- - * 4) LIB/notify contains only some of the known control message types.
- - * Action: initialize all addresses to "" and set declared addresses
- - * to listed address.
- - */
- -
- -control(h)
- -struct hbuf *h;
- -{
- - register char *ctlmsgtext;
- - register struct msgtype *mp;
- -
- - if (strncmp(h->title, "cmsg ", 5) == 0) {
- - register char *cp1, *cp2;
- - cp1 = h->title;
- - cp2 = h->title + 5;
- - while (*cp1++ = *cp2++)
- - ;
- - }
- -
- - if (*h->ctlmsg)
- - ctlmsgtext = h->ctlmsg;
- - else
- - ctlmsgtext = h->title;
- - log("Ctl Msg %s from %s: %s", h->nbuf, h->path, ctlmsgtext);
- - /*
- - * Control messages have the standard format
- - * command [args]
- - * much like shell commands. Each site has the option
- - * of customizing this code to deal with control messages
- - * as they see fit, but we would like to buy back the
- - * code, ifdeffed or otherwise parameterized, to simplify
- - * the maintenence issues.
- - */
- - argparse(ctlmsgtext);
- -
- - /*
- - * We look for a match of the control message name and then
- - * set TELLME to the value parsed from the LIB/notify file
- - * (if any).
- - */
- - for(mp=msgtype; mp->m_name; mp++) {
- - if(eq(mp->m_name) ) { /* hit */
- -#ifdef NOTIFY
- - TELLME = mp->m_who_to; /* reset whom to tell */
- -#endif /* NOTIFY */
- - if(strcmp(mp->m_name, "cancel") == 0) /* special case */
- - return (*mp->m_func)(cargc, cargv);
- - (*mp->m_func)(cargc, cargv); /* do the function */
- - break;
- - }
- - }
- - if( !mp->m_name ) {
- -#ifdef NOTIFY
- - TELLME = NOTIFY;
- -#endif /* NOTIFY */
- - c_unknown(h, ctlmsgtext);
- - }
- - return 0;
- -}
- -
- -/*
- - * Parse the string str into separate words in cargc and cargv
- - * as per the usual UNIX convention. Nothing fancy here, just
- - * blanks and tabs separating words.
- - */
- -argparse(str)
- -char *str;
- -{
- - static char *cavpbuf[20];
- - static char cavbuf[256];
- - char *nextfree = cavbuf;
- -
- - if (str == '\0')
- - error("Control message %s has no title", header.ident);
- - cargc = (*str != '\0');
- - cargv = cavpbuf;
- - cargv[0] = cavbuf;
- -
- - while (*str) {
- - if (*str <= ' ') {
- - *nextfree++ = 0;
- - cargv[cargc] = nextfree;
- - cargc++;
- - /* skip over white space */
- - while (*str != '\0' && *str <= ' ')
- - str++;
- - if (*str == '\0') /* line ends in white space */
- - return;
- - } else
- - *nextfree++ = *str++;
- - }
- -}
- -
- -/*
- - * ihave <artid> ... <remotesys>
- - * or
- - * ihave <remotesys>
- - * with <artid>s in message body.
- - *
- - * The other system is telling you it has article <artid>, in case
- - * you decide you want it to transmit it to you.
- - * The assumption is that the other system only tells you about articles
- - * in newsgroups you subscribe to.
- - *
- - * We turn the incoming ihave into an outgoing sendme on the fly.
- - * It then gets saved in the SPOOL directory and transmitted to the
- - * remote system. (This way the sendme messages can be batched.)
- - */
- -c_ihave(argc, argv)
- -register char ** argv;
- -{
- - register int i;
- - char list[sizeof header.title];
- - extern char * findhist();
- -
- - if (argc < 2)
- - error("ihave: Too few arguments.");
- - if (strncmp(FULLSYSNAME, argv[argc - 1], SNLN) == 0)
- - return;
- - list[0] = '\0';
- - if (argc > 2) {
- - for (i = 1; i < (argc - 1); ++i)
- - if (findhist(argv[i]) == NULL) {
- - (void) strcat(list, " ");
- - (void) strcat(list, argv[i]);
- - }
- - if (list[0] == '\0')
- - return;
- - } else {
- - register FILE * outfp;
- - register long outpos, inpos;
- - char myid[256];
- -
- - outfp = xfopen(INFILE, "a");
- - outpos = ftell(outfp);
- - inpos = ftell(infp);
- - while (ftell(infp) < outpos) {
- - if (fgets(myid, sizeof myid, infp) != myid)
- - error("iline: Can't rerear article");
- - myid[strlen(myid) - 1] = '\0';
- - if (findhist(myid) == NULL)
- - (void) fprintf(outfp, "%s\n", myid);
- - }
- - if (outpos == ftell(outfp)) { /* if nothing is wanted */
- - (void) fclose(outfp);
- - (void) fseek(infp, inpos, 0);
- - return;
- - }
- - (void) fclose(outfp);
- - /*
- - ** The close and open may just be paranoia.
- - */
- - (void) fclose(infp);
- - infp = xfopen(INFILE, "r");
- - (void) fseek(infp, outpos, 0);
- - }
- - /*
- - ** Turn the ihave into a sendme.
- - */
- - (void) sprintf(header.nbuf, "to.%s.ctl", argv[argc - 1]);
- - (void) sprintf(header.title, "sendme%s %s", list, FULLSYSNAME);
- - (void) strcpy(header.ctlmsg, header.title);
- - getident(&header);
- - (void) sprintf(header.from, "%s@%s%s", "usenet", FULLSYSNAME, MYDOMAIN);
- - (void) strcpy(header.path, NEWSUSR);
- - header.subdate[0] = header.expdate[0] = '\0';
- - dates(&header);
- - /*
- - ** What else of this kind should be done?
- - */
- - header.organization[0] = header.distribution[0] = '\0';
- - for (i = 0; i < NUNREC && header.unrec[i] != NULL; ++i) {
- - free(header.unrec[i]);
- - header.unrec[i] = NULL;
- - }
- - /*
- - ** Note that we do *not* change the history line
- - ** so that if the "ihave" message comes in again it gets rejected.
- - */
- -}
- -
- -/*
- - * sendme <artid> ... <remotesys>
- - * or
- - * sendme <remotesys>
- - * with <artid>s in message body.
- - * The other system wants me to send out article <artid>.
- - * Give it to them with no fuss.
- - */
- -c_sendme(argc, argv)
- -register char ** argv;
- -{
- - struct srec srec;
- -
- - if (argc < 2)
- - error("sendme: Too few arguments.");
- - if (strncmp(FULLSYSNAME, argv[argc - 1], SNLN) == 0)
- - return;
- - if (s_find(&srec, argv[argc - 1]) != TRUE)
- - error("sendme: Can't find sys record for %s", argv[argc - 1]);
- - /* Send the articles. */
- - if (argc == 2) {
- - register FILE * fp;
- - char buf[256];
- -
- - fp = xfopen(INFILE, "r");
- - while (fgets(buf, sizeof buf, fp) == buf) {
- - buf[strlen(buf) - 1] = '\0'; /* zap trailing '\n' */
- - sendmefunc(buf, &srec);
- - }
- - (void) fclose(fp);
- - } else { /* argc > 2 */
- - register int i;
- -
- - for (i = 1; i < (argc - 1); ++i)
- - sendmefunc(argv[i], &srec);
- - }
- -}
- -
- -static
- -sendmefunc(id, sp)
- -register char * id;
- -register struct srec * sp;
- -{
- - register FILE * fp;
- - register char * cp;
- - char savedbufname[256];
- - extern char firstbufname[];
- - extern char * dirname();
- - extern char * findfname();
- -
- - cp = findfname(id);
- - if (cp == NULL) {
- - logerr("System %s wants unavailable article %s.",
- - sp->s_name, id);
- - return;
- - }
- - cp = dirname(cp);
- - fp = fopen(cp, "r");
- - if (fp == NULL) {
- - logerr("Article %s unopenable as %s.", id, cp);
- - return;
- - }
- - (void) strcpy(savedbufname, firstbufname);
- - (void) strcpy(firstbufname, cp);
- - transmit(sp, fp, FALSE, (char **) NULL, FALSE);
- - /* transmit closes fp */
- - (void) strcpy(firstbufname, savedbufname);
- -}
- -
- -/*
- - * newgroup <groupname>
- - * A new newsgroup has been created.
- - * The body of the article, if present, is a description of the
- - * purpose of the newsgroup.
- - *
- - */
- -c_newgroup(argc, argv)
- -char **argv;
- -{
- - FILE *fd;
- - char abuf[BUFLEN], subjline[BUFLEN];
- - int didcreate = 0;
- - register char *p, *q;
- -# ifdef NONEWGROUPS
- -# ifdef ORGDISTRIB
- - /* local or ORGDISTRIB */
- - int can_change = (strcmp(header.distribution, "local") == 0) ||
- - (strcmp(header.distribution, ORGDISTRIB) == 0);
- -# else /* ! ORGDISTRIB */
- - /* local only */
- - int can_change = strcmp(header.distribution, "local") == 0;
- -# endif /* ORGDISTRIB */
- -# else /* ! NONEWGROUPS */
- - int can_change = 1; /* allow changes for all distributions */
- -# endif /* NONEWGROUPS */
- -
- - if (argc < 2)
- - error("newgroup: Too few arguments.");
- -
- - if (header.approved[0] == '\0')
- - error("newgroup: %s not approved", argv[1]);
- -
- - /* see if it already exists */
- - (void) rewind(actfp); clearerr(actfp);
- - while(fgets(abuf, BUFLEN, actfp) != NULL) {
- - p = abuf;
- - q = argv[1];
- - while (*p++ == *q++)
- - ;
- - if (*--q == '\0' && *--p == ' ') {
- - int modified = 0;
- - /* Now check if it's correctly moderated/unmoderated */
- - while (*p++)
- - ;
- - p -= 3;
- - if (argc > 2 && strcmp(argv[2], "moderated") == 0) {
- - if (*p == 'm')
- - return;
- -# ifdef NONEWGROUPS
- - if(can_change) {
- - *p = 'm';
- - modified = 1;
- - }
- -# else /* ! NONEWGROUPS */
- - *p = 'm';
- - modified = 1;
- -#endif /* NONEWGROUPS */
- - } else {
- - if (*p != 'm')
- - return;
- -# ifdef NONEWGROUPS
- - if(can_change) {
- - *p = 'y';
- - modified = 1;
- - }
- -# else /* ! NONEWGROUPS */
- - *p = 'y';
- - modified = 1;
- -# endif /* NONEWGROUPS */
- - }
- -# ifdef NOTIFY
- - (void) sprintf(subjline,
- - "Newsgroup %s change from %smoderated to %smoderated",
- - argv[1], *p=='y' ? "" : "un",
- - *p=='y' ? "un" : "");
- - fd = mailhdr((struct hbuf *)NULL, subjline);
- - if (fd != NULL) {
- - if(modified)
- - fprintf(fd,
- -"%s has been changed from %smoderated to %smoderated as requested by\n%s\n",
- - argv[1], *p=='y' ? "" : "un",
- - *p=='y' ? "un":"", header.path);
- - else {
- - fprintf(fd,
- -"%s\nhas requested that %s be changed from %smoderated to %smoderated\n",
- - header.path, argv[1],
- - *p=='y' ? "un" : "",
- - *p=='y' ? "" : "un");
- -#ifdef ORGDISTRIB
- - fprintf(fd,
- -"You can accomplish this by re-creating the newsgroup with a distribution\n");
- - fprintf(fd,
- -"of '%s' by executing the command:\n", ORGDISTRIB);
- - fprintf(fd,
- - "%s/inews -d %s -C %s moderated\n",
- - LIB, ORGDISTRIB, argv[1]);
- -#else /* !ORGDISTRIB */
- - fprintf(fd,
- -"You can accomplish this by re-creating the newsgroup by executing the command:\n");
- - fprintf(fd, "%s/inews -C %s moderated\n",
- - LIB, argv[1]);
- -#endif /* !ORGDISTRIB */
- - }
- - (void) mclose(fd);
- - }
- -# endif /* NOTIFY */
- -# ifdef NONEWGROUPS
- - /*
- - * No permission to change
- - */
- - if(!can_change)
- - return;
- -# endif /* NONEWGROUPS */
- - /* The active file was wrong about the state of the
- - * group. Rewrite the active file
- - */
- - (void) fseek(actfp, -2L, 1); /* back up 2 characters */
- -#ifdef USG
- - /*
- - * U G L Y K L U D G E
- - * This utter piece of tripe is the only way I know of
- - * to get around the fact that ATT BROKE standard IO
- - * in System 5.2. Basically, you can't open a file for
- - * "r+" and then try and write to it. This hack works
- - * on all "real" USG Unix systems, It will probably
- - * break on some obscure look alike that doesnt use the
- - * real ATT stdio.h
- - * Don't blame me, blame ATT. stdio should have
- - * already done the following line for us, but it didn't
- - */
- - actfp->_flag |= _IOWRT;
- -#endif /* USG */
- - putc(*p, actfp);
- - fflush(actfp);
- - if (*p != 'm')
- - logerr("Newsgroup %s changed from moderated to unmoderated",
- - argv[1]);
- - else
- - logerr("Newsgroup %s changed from unmoderated to moderated",
- - argv[1]);
- - return;
- - }
- - }
- -
- - /* It doesn't already exist, we must create it */
- -
- - if(can_change) {
- - didcreate++;
- - (void) fseek(actfp, 0L, 2); clearerr(actfp);
- - fprintf(actfp, "%s 00000 00001 %c\n", argv[1],
- - (argc > 2 && strcmp(argv[2], "moderated") == 0)
- - ? 'm' : 'y');
- - fflush(actfp);
- - }
- -
- -# ifdef NOTIFY
- - (void) sprintf(subjline, "Newsgroup %s created", argv[1]);
- - fd = mailhdr((struct hbuf *)NULL, subjline);
- - if (fd != NULL) {
- - if (didcreate)
- - fprintf(fd,
- - "A new newsgroup called '%s' has been created by %s.\n",
- - argv[1], header.path);
- - else {
- - fprintf(fd,
- - "%s requested that a new newsgroup called '%s' be created.\n",
- - header.path, argv[1]);
- - fprintf(fd,"It was approved by %s\n\n",header.approved);
- - fprintf(fd,
- - "You can accomplish this by creating the newgroup yourself\n");
- -# ifdef ORGDISTRIB
- - fprintf(fd,"with a distribution of '%s'.\n",
- - ORGDISTRIB);
- - fprintf(fd,
- - "In other words, by executing the command:\n");
- - fprintf(fd, "%s/inews -d %s -C %s\n", LIB,
- - ORGDISTRIB, argv[1]);
- -# else /* !ORGDISTRIB */
- - fprintf(fd, "In other words, by executing the command:\n");
- - fprintf(fd, "%s/inews -C %s\n", LIB, argv[1]);
- -# endif /* !ORGDISTRIB */
- - }
- - (void) mclose(fd);
- - }
- -# endif /* NOTIFY */
- -}
- -
- -/*
- - * rmgroup <groupname>
- - * An old newsgroup is being cancelled on a network wide basis.
- - */
- -c_rmgroup(argc, argv)
- -char **argv;
- -{
- - FILE *fd;
- - int shouldremove = 0;
- -#ifdef NOTIFY
- - char subjline[BUFLEN];
- -#endif /* NOTIFY */
- -
- - if (argc < 2)
- - error("rmgroup: Too few arguments.");
- - if (!validng(argv[1]))
- - return;
- - if (header.approved[0] == '\0')
- - error("rmgroup: %s not approved", argv[1]);
- -
- -#ifndef MANUALLY
- -#ifdef ORGDISTRIB
- - /*
- - * Allow local as well as organizational removals
- - */
- - if (!strcmp(ORGDISTRIB, header.distribution)
- - || !strcmp("local", header.distribution))
- -#else /* !ORGDISTRIB */
- - if (!strcmp("local", header.distribution))
- -#endif /* !ORGDISTRIB */
- - shouldremove++;
- -#endif /* !MANUALLY */
- -#ifdef NOTIFY
- - sprintf(subjline, "Recevied rmgroup for %s", argv[1]);
- - fd = mailhdr((struct hbuf *)NULL, subjline);
- - if (fd != NULL) {
- - if (shouldremove) {
- - fprintf(fd, "Newsgroup '%s' has been removed by %s.\n\n",
- - argv[1], header.path);
- -# ifdef USG
- - fprintf(fd, "You may need to remove the directory %s by hand\n",
- - dirname(argv[1]));
- -# endif
- - } else {
- - fprintf(fd, "%s requested that newsgroup %s be removed.\n",
- - header.path, argv[1]);
- - fprintf(fd, "You should remove it by hand\n");
- - fprintf(fd, "To do this, execute the command\n");
- - fprintf(fd, "\t%s/rmgroup %s\n", LIB, argv[1]);
- - }
- - (void) mclose(fd);
- - }
- -#endif /* NOTIFY */
- -
- - if (shouldremove) {
- - int rc;
- - /* We let the shell do all the work.
- - * See the rmgrp shell script. */
- - (void) setuid(geteuid()); /* otherwise it won't rmdir the dir */
- - (void) sprintf(bfr, "exec %s/rmgroup %s", LIB, argv[1]);
- - rc = system(bfr);
- - log("system(%s) status %d", bfr, rc);
- - }
- -}
- -
- -/*
- - * cancel <artid>
- - * Cancel the named article
- - */
- -c_cancel(argc, argv)
- -char **argv;
- -{
- - char *line, *p, *q, *r, *poster;
- - char *findhist();
- - register FILE *fp;
- - char whatsisname[BUFLEN], nfilename[BUFLEN];
- - time_t t;
- - int su = 0;
- -#ifndef u370
- - struct hbuf htmp;
- -#endif /* !u370 */
- -
- - if (argc < 2)
- - error("cancel: Too few arguments.");
- - (void) strcpy(whatsisname, senderof(&header));
- - line = findhist(argv[1]);
- - if (line == NULL) {
- - struct tm *tm;
- - log("Can't cancel %s: non-existent", argv[1]);
- - (void) time(&t);
- - tm = localtime(&t);
- -#ifdef USG
- - sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled",
- -#else /* !USG */
- - sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled",
- -#endif /* !USG */
- - argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour,
- - tm->tm_min);
- - savehist(bfr);
- - return 1;
- - }
- -
- - q = index(line, '\t');
- - p = index(q+1, '\t');
- - if (p == NULL || *++p == '\0' || *p == '\n') {
- - *q = '\0';
- - log("Expired article %s", line);
- - return 1;
- - }
- - if (strcmp(p, "cancelled") == 0) {
- - *q = '\0';
- - log("Already Cancelled %s", line);
- - return 1;
- - } else
- - log("Cancelling %s", line);
- - if ((uid == ROOTID||uid == 0) && strcmp(header.distribution, "local") == 0)
- - su = 1;
- - while (*p) {
- - q = index(p, ' ');
- - if (q)
- - *q = '\0';
- - (void) strcpy(nfilename, dirname(p));
- - fp = fopen(nfilename, "r");
- - if (fp == NULL) {
- - log("Already Cancelled %s", line);
- - return 1;
- - }
- - htmp.unrec[0] = NULL;
- - if (hread(&htmp, fp, TRUE) == NULL) {
- - if (bfr[0] == '/') {
- - fp = fopen(bfr, "r");
- - if (fp == NULL
- - || hread(&htmp, fp, TRUE) == NULL)
- - error("Article is garbled.");
- - } else
- - error("Article is garbled.");
- - }
- - (void) fclose(fp);
- - poster = senderof(&htmp);
- - /* only compare up to '.' or ' ' */
- - r = index(poster,'.');
- - if (r == NULL)
- - r = index(poster,' ');
- - if (r != NULL)
- - *r = '\0';
- - if (!su && strncmp(whatsisname, poster,strlen(poster))) {
- - error("Not contributor: posted by %s, and you are %s", poster, whatsisname);
- - }
- -
- - (void) unlink(nfilename);
- - p = q+1;
- - }
- - return 0;
- -}
- -
- -/*
- - * sendsys (no arguments)
- - *
- - * Mail the sys file to the person submitting the article.
- - * POLICY: the contents of your sys file are public information
- - * and as such, you should not change this code. You may feel
- - * free to arrange for it to manually notify you, in the event
- - * that you want to do something to clean it up before it goes out.
- - * Secret sites on the net are expressly frowned on.
- - *
- - * The purpose of this command is for making a network map. The
- - * details of your link and which newsgroups are forwarded are not
- - * important, in case you want to sanitize them. Since the definition
- - * of USENET is those sites getting net.announce, you can disable this
- - * on sites not getting net articles, but if you take out the list of
- - * forwarded newsgroups, and you have sites that only get local newsgroups,
- - * you should make this clear, or remove those sites from what you send out.
- - */
- -/* ARGSUSED */
- -c_sendsys(argc, argv)
- -char **argv;
- -{
- - register FILE *f, *u;
- - int c;
- -
- -#ifdef NOTIFY
- - f = mailhdr((struct hbuf *)NULL, "sendsys control message");
- - if (f != NULL) {
- - fprintf(f, "%s requested your %s/sys file.\n", header.path, LIB);
- - fprintf(f, "It has been sent.\n");
- - (void) mclose(f);
- - }
- -#endif /* NOTIFY */
- - f = mailhdr(&header, "response to your sendsys request");
- - u = fopen(SUBFILE, "r");
- - if (f != NULL && u != NULL) {
- - while ((c=getc(u)) != EOF)
- - putc(c, f);
- - (void) fclose(u);
- - (void) mclose(f);
- - }
- -}
- -
- -/*
- - * senduuname (no arguments)
- - *
- - * Run the "uuname" command and send it back to the person who submitted
- - * the article. The purpose of this control message is for attempting to
- - * make a uucp net map.
- - *
- - * POLICY: If you view this information as not public (because you have
- - * a connection you consider secret, or know a site that considers itself
- - * secret) you can feel free to change this code in whatever way is
- - * appropriate, so long as it sends some response back to the sender. If
- - * you don't run uucp, this code does not make sense, and so an error
- - * message (or garbage, such as "research") will be mailed back.
- - *
- - * If you wish to add or remove sites from the output of uuname, you
- - * may wish to use the euuname.sh shell script here.
- - */
- -/* ARGSUSED */
- -c_senduuname(argc, argv)
- -char **argv;
- -{
- - char buf[256];
- - FILE *fd, *u;
- - int c;
- -
- -#ifdef NOTIFY
- - fd = mailhdr((struct hbuf *)NULL, "uuname control message");
- - fprintf(fd, "%s requested your uuname output\n", header.path);
- - (void) mclose(fd);
- -#endif /* NOTIFY */
- - fd = mailhdr(&header, "response to your senduuname request");
- -#ifdef UUPROG
- - if (UUPROG[0] == '/')
- - (void) strcpy(buf, UUPROG);
- - else
- - (void) sprintf(buf, "%s/%s", LIB, UUPROG);
- -#else
- - (void) strcpy(buf, "uuname");
- -#endif
- - u = popen(buf, "r");
- - if (fd != NULL && u != NULL) {
- - while ((c=getc(u)) != EOF)
- - putc(c, fd);
- - (void) pclose(u);
- - (void) mclose(fd);
- - }
- -}
- -
- -/*
- - * Send the version number to the right person.
- - */
- -/* ARGSUSED */
- -c_version(argc, argv)
- -char **argv;
- -{
- - register FILE *f;
- -
- - f = mailhdr(&header, "Our news version");
- - if (f == NULL)
- - error("Cannot send back error message");
- - fprintf(f, "Currently running news version %s.\n\n", news_version);
- - fprintf(f, "The header of your message follows:\n\n");
- - (void) hwrite(&header, f);
- - (void) mclose(f);
- -}
- -
- -/*
- - * Check the active file for old or missing newsgroups
- - * Body of article is list of valid groups
- - */
- -/* ARGSUSED */
- -c_checkgroups(argc, argv)
- -char **argv;
- -{
- - int rc;
- -
- - (void) setuid(geteuid());
- - /* dont change the cat %s| to < %s, it breaks some "unix" systems */
- - (void) sprintf(bfr, "cat %s | %s/checkgroups %s", INFILE, LIB,
- -#ifdef NOTIFY
- - (TELLME && *TELLME) ? TELLME : NEWSUSR );
- -#else /* !NOTIFY */
- - NEWSUSR);
- -#endif /* !NOTIFY */
- - rc = system(bfr);
- - log("system(%s) status %d", bfr, rc);
- -}
- -
- -/*
- - * An unknown control message has been received.
- - */
- -c_unknown(h, ctlmsgtext)
- -struct hbuf *h;
- -char *ctlmsgtext;
- -{
- - register FILE *f;
- -
- - log("UNKNOWN Ctl Msg %s from %s", ctlmsgtext, h->path);
- -#ifdef NOTIFY
- - f = mailhdr((struct hbuf *)NULL, "Unrecognized Control Message");
- - if (f != NULL) {
- - fprintf(f, "Currently running news version %s.\n\n", news_version);
- - fprintf(f, "The header of the message follows:\n\n");
- - (void) hwrite(h, f);
- - (void) mclose(f);
- - }
- -#endif /* NOTIFY */
- -}
- -
- -/* ARGSUSED */
- -c_unimp(argc, argv)
- -char **argv;
- -{
- - register FILE *f;
- -
- -#ifdef NOTIFY
- - f = mailhdr((struct hbuf*)NULL, "Unimplemented Control Message");
- - if (f != NULL) {
- - fprintf(f, "Currently running news version B %s.\n\n", news_version);
- - fprintf(f, "The header of the message follows:\n\n");
- - (void) hwrite(&header, f);
- - (void) mclose(f);
- - }
- -#endif /* NOTIFY */
- -}
- -
- -/*
- - * This is a modified version of popen, made more secure. Rather than
- - * forking off a shell, you get a bare process. You must have exactly
- - * one argument, and the command must be mail (or sendmail if you have it).
- - */
- -#define RDR 0
- -#define WTR 1
- -static int mopen_pid[20];
- -char *replyname();
- -
- -FILE *
- -mhopen(hptr)
- -struct hbuf *hptr;
- -{
- - int p[2];
- - register myside, hisside, pid;
- - char *sendto = "usenet";
- -
- - if (hptr)
- - sendto = replyname(hptr);
- - else {
- -#ifdef NOTIFY
- - if (TELLME)
- - sendto = TELLME;
- -#endif /* NOTIFY */
- - if (sendto == NULL || *sendto == NULL)
- - return NULL;
- - }
- - verifyname(sendto);
- - if(pipe(p) < 0)
- - return NULL;
- - myside = p[WTR];
- - hisside = p[RDR];
- - if((pid = vfork()) == 0) {
- - /* myside and hisside reverse roles in child */
- - (void) close(myside);
- - (void) close(0);
- - (void) dup(hisside);
- - (void) close(hisside);
- - (void) setgid(gid);
- - (void) setuid(uid);
- -#ifdef SENDMAIL
- - execl(SENDMAIL, "sendmail", "-oi", "-oeq", sendto, (char *)NULL);
- -#endif /* SENDMAIL */
- -#ifdef MMDF
- - execl(MMDF, "inews-mail", "-smuxto,cc*", (char *)NULL);
- -#endif /* MMDF */
- - execl("/bin/mail", "mail", sendto, (char *)NULL);
- - execl("/usr/bin/mail", "mail", sendto, (char *)NULL);
- - execl("/usr/ucb/mail", "mail", sendto, (char *)NULL);
- - _exit(1);
- - }
- - if(pid == -1)
- - return NULL;
- - mopen_pid[myside] = pid;
- - (void) close(hisside);
- - return(fdopen(myside, "w"));
- -}
- -
- -mclose(ptr)
- -FILE *ptr;
- -{
- - register f, r, (*hstat)(), (*istat)(), (*qstat)();
- - int status;
- -
- - f = fileno(ptr);
- - (void) fclose(ptr);
- - istat = signal(SIGINT, SIG_IGN);
- - qstat = signal(SIGQUIT, SIG_IGN);
- - hstat = signal(SIGHUP, SIG_IGN);
- - while((r = wait(&status)) != mopen_pid[f] && r != -1)
- - ;
- - if(r == -1)
- - status = -1;
- - signal(SIGINT, istat);
- - signal(SIGQUIT, qstat);
- - signal(SIGHUP, hstat);
- - return status;
- -}
- -
- -/*
- - * mhopen a pipe to mail, write out a std header, and return the file ptr.
- - *
- - * We don't include a From: field because this is probably uucp, i.e.
- - * explicitly routed. Leave it up to the recipient's mailer.
- - * Always include the To: field because if we ge back failed mail, we
- - * might be able to deliver it by hand if we know to wom it was addressed.
- - * By convention, hptr==NULL means to send the message to the local contact person.
- - */
- -FILE *
- -mailhdr(hptr, subject)
- -struct hbuf *hptr;
- -char *subject;
- -{
- - FILE *fp;
- - time_t now;
- - char *to = "usenet";
- -
- -#ifdef NOTIFY
- - if (TELLME && *TELLME)
- - to = TELLME;
- -#endif /* NOTIFY */
- - if (hptr)
- - to = replyname(hptr);
- -
- - if ((fp = mhopen(hptr)) != NULL) {
- - (void) time(&now);
- - fprintf(fp, "Date: %s\n", arpadate(&now));
- -#ifdef MMDF
- - fprintf(fp, "From: The News System <usenet@%s%s>\n",
- - FULLSYSNAME, MYDOMAIN);
- -#endif /* MMDF */
- - fprintf(fp, "To: %s\n", to);
- - fprintf(fp, "Subject: %s\n", subject);
- -#ifdef HIDDENNET
- - if (strcmp(LOCALSYSNAME, FULLSYSNAME))
- - fprintf(fp, "Responding-System: %s.%s%s\n\n",
- - LOCALSYSNAME, FULLSYSNAME, MYDOMAIN);
- - else
- -#endif /* !HIDDENNET */
- - fprintf(fp, "Responding-System: %s%s\n\n",
- - FULLSYSNAME, MYDOMAIN);
- - }
- - return fp;
- -}
- -
- -/*
- - * verify that the name mail is being sent to does not contain any
- - * nasty hooks to invoke funny functions from the shell or the like.
- - */
- -verifyname(sendto)
- -char *sendto;
- -{
- - /* Be sure we DO allow alphabetics, !, :, ., -, @. *. */
- - char *nasty = "\"'\\`^|;& <>/~";
- - register char *p;
- -
- - if (sendto[0] <= ' ') {
- - log("nasty mail name %s from %s", sendto, header.path);
- - xxit(1);
- - }
- - for (p=sendto; *p; p++) {
- - if (*p == ' ') {
- - *p = 0;
- - break;
- - }
- - }
- - if (strpbrk(sendto, nasty) != NULL)
- - error("nasty mail name %s from %s", sendto, header.path);
- -
- - for (nasty = sendto; (nasty = index(nasty, '.')) != NULL; ) {
- - if (*++nasty == '.') /* check for .. */
- - error("nasty mail name %s from %s", sendto, header.path);
- - }
- -}
- -
- -/*
- - * Checks to make sure the control message is OK to post.
- - */
- -ctlcheck()
- -{
- - char msg[BUFLEN];
- - char *p;
- -
- - if (!is_ctl)
- - return;
- -
- - if (header.ctlmsg[0])
- - (void) strcpy(msg, header.ctlmsg);
- - else
- - (void) strcpy(msg, header.title);
- -
- - p = index(msg, ' ');
- - if (p)
- - *p = 0;
- -
- - if (strcmp(msg, "ihave") == 0 || strcmp(msg, "sendbad") == 0 ||
- - strcmp(msg, "sendme") == 0) {
- - return; /* no restrictions */
- - } else if (strcmp(msg, "newgroup") == 0) {
- - suser();
- - } else if (strcmp(msg, "rmgroup") == 0) {
- - suser();
- - } else if (strcmp(msg, "sendsys") == 0) {
- - suser();
- - } else if (strcmp(msg, "senduuname") == 0) {
- - suser();
- - } else if (strcmp(msg, "checkgroups") == 0) {
- - suser();
- - } else if (strcmp(msg, "version") == 0) {
- - return; /* no restrictions */
- - } else if (strcmp(msg, "cancel") == 0) {
- - return; /* no restrictions at this level */
- - } else if (strcmp(msg, "delsub") == 0) {
- - if (!prefix(header.nbuf, "to.")) {
- - printf("Must be in a 'to.system' newsgroup.");
- - xxit(0);
- - }
- - return;
- - } else {
- - printf("Unrecognized control message - %s\n", msg);
- - xxit(0);
- - }
- -}
- -
- -/* Make sure this guy is special. */
- -suser()
- -{
- - if (uid == 0 || uid == ROOTID)
- - return;
- - /*
- - * We assume that since our real uid is the same as NEWSUSR
- - * (the euid) we were run by rootid and it did a setuid.
- - * Too bad we can't set just the effective uid like suid does.
- - */
- - if (uid == geteuid())
- - return;
- -#ifdef IHCC
- - printf("Please use the command:\n\ttoolnews providers\n");
- - printf("then call one of the news people.\n");
- -#else
- - printf("Get your local netnews contact to do it for you.\n");
- -#endif
- - xxit(0);
- -}
- *-*-END-of-src/control.c-*-*
- echo x - src/unbatch.c 1>&2
- sed 's/.//' >src/unbatch.c <<'*-*-END-of-src/unbatch.c-*-*'
- -/*
- - * unbatchnews: extract news in batched format and process it one article
- - * at a time. The format looks like
- - * #! rnews 1234
- - * article containing 1234 characters
- - * #! rnews 4321
- - * article containing 4321 characters
- - *
- - * or
- - *
- - * #! command [args]
- - * calls LIBDIR/command [args] to process the news
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)unbatch.c 1.22 10/23/86";
- -#endif /* SCCSID */
- -
- -#define MAXARGS 20
- -
- -#include "defs.h"
- -#include <stdio.h>
- -#include <ctype.h>
- -#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
- -#include <fcntl.h>
- -#endif /* USG */
- -
- -char buf[BUFSIZ];
- -char sibuf[BUFSIZ];
- -
- -main()
- -{
- - register int c;
- - register FILE *pfn;
- - register long size;
- - char *filename;
- - int pid, wpid, exstat;
- - char *mktemp(), *gets();
- - long atol();
- -
- - filename = mktemp("/tmp/unbnewsXXXXXX");
- - setbuf(stdin, (char *)NULL); /* only for the first line */
- - if (gets(buf) == NULL) {
- - (void) unlink(filename);
- - exit(0);
- - }
- - if (strncmp(buf, "#! rnews ", 9) != 0) {
- - docmd(buf);
- - /* should not return */
- - logerr("unbatch: docmd returned!");
- - exit(1);
- - }
- -
- - setbuf(stdin, sibuf); /* buffer the rest of the file */
- -
- - do {
- - while (strncmp(buf, "#! rnews ", 9)
- - && strncmp(buf, "! rnews ", 8)) { /* kludge for bug */
- - register char *cp;
- - for (cp = buf; *cp != '\0'; ++cp)
- - if (!isascii(*cp) ||
- - (!isprint(*cp) && !isspace(*cp)))
- - *cp = '?';
- - logerr("out of sync, skipping %s", buf);
- - if (gets(buf) == NULL)
- - exit(0);
- - }
- - size = atol(buf + (buf[0] == '#' ? 9 : 8));
- - if(size <= 0) {
- - logerr("nonsense size %ld", size);
- - continue;
- - }
- -#ifdef VMS
- -/* The loop is to delete all versions. */
- - while (unlink(filename) == 0)
- - ;
- -#endif /* VMS */
- - pfn = fopen(filename, "w");
- - while(--size >= 0 && (c = getc(stdin)) != EOF)
- - putc(c, pfn);
- - if (ferror(pfn) || fclose(pfn)) { /* disk full? */
- - logerr("error writing temporary file");
- - break;
- - }
- -
- - /*
- - * If we got a truncated batch, don't process the
- - * last article; it will probably be received again.
- - */
- - if (size > 0) {
- - logerr("truncated batch");
- - break;
- - }
- -
- - /*
- - * rnews < filename
- - */
- - while ((pid = vfork()) == -1) {
- - logerr("fork failed, waiting...\n");
- - sleep(60);
- - }
- - if (pid == 0) {
- - (void) close(0);
- - (void) open(filename, 0);
- -#ifdef IHCC
- - (void) sprintf(buf, "%s/%s/rnews", logdir(HOME), LIBDIR);
- -#else
- - (void) sprintf(buf, "%s/rnews", BINDIR);
- -#endif
- -#ifdef SPOOLNEWS
- - execlp(buf, "rnews", "-S", (char *)0);
- -#else /* !SPOOLNEWS */
- - execlp(buf, "rnews", (char *)0);
- -#endif /* !SPOOLNEWS */
- - perror("rnews");
- - exit(1);
- - }
- - while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
- - ;
- - } while (gets(buf) != NULL);
- - (void) unlink(filename);
- - exit(0);
- -}
- -
- -docmd(p)
- -register char *p;
- -{
- - char *args[MAXARGS];
- - register char **ap = args;
- - char path[BUFSIZ];
- - char *rindex(), *cp;
- -
- - while (*p && !isspace(*p)) /* skip leading #! crud */
- - p++;
- -
- - while (isspace(*p))
- - p++;
- -
- - while (*p != '\0') {
- - *ap++ = p;
- - if (ap >= &args[MAXARGS]) {
- - logerr("unbatch: Too many args to %s", args[0]);
- - exit(2);
- - }
- - while (*p && !isspace(*p))
- - p++;
- - if (*p)
- - *p++ = '\0';
- - while (isspace(*p))
- - p++;
- - }
- - *ap = (char *)0;
- -
- - if (ap == args) {
- - logerr("unbatch: no command to execute");
- - exit(2);
- - }
- -
- - /* strip off any leading pathname in case someone gets tricky */
- - cp = rindex(args[0], '/');
- - if (cp++ == NULL)
- - cp = args[0];
- -
- - sprintf(path, "%s/%s", LIBDIR, cp);
- -
- - /*
- - * "path" is absolute, no searching is needed, we use
- - * 'execvp' solely so that sh scripts will be handled
- - */
- - (void) execvp(path, args);
- - perror(path);
- - exit(2);
- -}
- -
- -/*
- - * Log the given message, with printf strings and parameters allowed,
- - * on the log file, if it can be written.
- - */
- -/* VARARGS1 */
- -logerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
- -char *fmt;
- -{
- - FILE *logfile;
- - char lfname[BUFSIZ]; /* the log file */
- - char bfr[BUFSIZ];
- - char *logtime, *ctime();
- - long t;
- -
- - (void) time(&t);
- - logtime = ctime(&t);
- - logtime[16] = 0;
- - logtime += 4;
- -
- -#ifdef IHCC
- - (void) sprintf(lfname, "%s/%s/errlog", logdir(HOME), LIBDIR);
- -#else
- - (void) sprintf(lfname, "%s/errlog", LIBDIR);
- -#endif
- -
- - (void) sprintf(bfr, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
- - (void) fprintf(stderr, "%s\n", bfr);
- - if (access(lfname, 0) == 0 && (logfile = fopen(lfname, "a")) != NULL) {
- -#if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
- - int flags;
- - flags = fcntl(fileno(logfile), F_GETFL, 0);
- - (void) fcntl(fileno(logfile), F_SETFL, flags|O_APPEND);
- -#else /* v7 */
- - (void) lseek(fileno(logfile), 0L, 2);
- -#endif /* v7 */
- - fprintf(logfile, "%s\tbatch\t%s\n", logtime, bfr);
- - (void) fclose(logfile);
- - }
- -}
- *-*-END-of-src/unbatch.c-*-*
- echo x - src/euninstal.com 1>&2
- sed 's/.//' >src/euninstal.com <<'*-*-END-of-src/euninstal.com-*-*'
- -$ ! @(#)euninstal.com 1.2 10/28/86
- -$ ! This DCL script installs inews and rnews with the necessary
- -$ ! privileges in a Eunice system.
- -$ SET PROCESS/PRIV=CMKRNL
- -$ RUN SYS$SYSTEM:INSTALL
- -EUN_USR:[USR.BIN]RNEWS. /OPEN/SHARED/PRIV=SYSPRV
- -EUN_USR:[USR.LIB.NEWS]INEWS. /OPEN/SHARED/PRIV=SYSPRV
- -$ EXIT
- *-*-END-of-src/euninstal.com-*-*
- exit
-
-